package it.blog.server;

import java.io.*;
import java.sql.*;
import java.util.*;

import org.jdom.*;
import org.jdom.input.*;

/**
 * Gestisce le connessioni al database.
 * Mantiene una lista di connessioni al database, utilizzate per ridurre l'overhead
 * per la creazione di una connessione ad ogni richiesta.
 *
 */
class ConnectionManager implements IConnection {
			
	private String classdriver;
	private String url;
	private String username;
	private String password;	
	private int maxConnections;
	private LinkedList<Connection> connections;
		
	
	public ConnectionManager(){
		ArrayList<String> dbparameters = this.readConfigurationFromXML();
		if(dbparameters!=null){
			try {
				Class.forName(dbparameters.get(1));
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
			connections = new LinkedList<Connection>();
			maxConnections = Integer.parseInt(dbparameters.get(0));
			url = dbparameters.get(2);	
			username = dbparameters.get(3);
			password = dbparameters.get(4);
		}
		
	}
	
	public ConnectionManager(String driver, String url, String user, String password,int numberConnections){
		classdriver = driver;
		try {
			Class.forName(classdriver);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		this.url = url;
		connections = new LinkedList<Connection>();
		maxConnections = numberConnections;
		username = user;
		this.password = password;
	}

	@Override
	public synchronized Connection getConnection() {

		while (connections.size() > 0) {
			Connection conn = (Connection) connections.removeFirst();
			if (validConnection(conn))
				return conn;
			else {
				try {
					conn.close();
				} catch (SQLException ex) {
				}
			}
		}

		// Non potendo riciclare, crea una nuova connessione
		try {
			Connection conn = DriverManager.getConnection(url, username,
					password);
			return conn;
		} catch (SQLException ex) {
			ex.printStackTrace();
			throw new RuntimeException("Non e' possibile connettersi al DB");
		}
	}


	@Override
	public synchronized void recycleConnection(Connection conn) {
		connections.addLast(conn);
		while (connections.size() > maxConnections) {
			Connection c = (Connection) connections.removeFirst();
			try {
				c.close();
			} catch (SQLException ex) {
			}
		}
	}

	/**
	 * Verifica se una connessione e' valida
	 * 
	 * @param conn connessione da verificare
	 * @return <code>true</code> se la connessione e' valida
	 */
	private boolean validConnection(Connection conn) {
		try {
			Statement stmt = conn.createStatement();
			stmt.executeQuery("SELECT 1;");
		} catch (SQLException ex) {
			return false;
		}
		return true;
	}
	
	
	private ArrayList<String> readConfigurationFromXML(){
		try { 
	      SAXBuilder builder = new SAXBuilder(); 
	      Document document = builder.build(new File("webapps/BlogProject/WEB-INF/config.xml")); 
	      ArrayList<String> connectionvar = new ArrayList<String>();
	      
	       //Prendo la radice 
	      Element root = document.getRootElement(); 
	      //Estraggo i figli dalla radice 
	      List children = root.getChildren(); 
	      Iterator iterator = children.iterator(); 
	       //Per ogni figlio 
	      while(iterator.hasNext()){
	    	  Element item = (Element)iterator.next();
	    	  List childrenlev2 = item.getChildren();
	    	  Iterator iteratorlev2= childrenlev2.iterator();
	    	  
			while(iteratorlev2.hasNext()){
				Element item2 = (Element)iteratorlev2.next();
	    		connectionvar.add(item2.getText());
	    		
			}
	      }return connectionvar;
	    
		}catch (Exception e) { 
		      System.err.println("Errore durante la lettura dal file"); 
		      e.printStackTrace(); 
		      return null;
		}
	}
	
	
	

}
